<?php
namespace App\Utilitys;

class FFbase
{
    /**
     * 使用FFmpeg
     */

    protected $ffmpeg; //FFmpeg软件的目录地址
    protected $prefix; //合成后文件地址前缀
    protected $log;

    public function __construct()
    {
        $this->ffmpeg = 'ffmpeg';
        $this->prefix = '/www/liujiu/quanzi/public/';
        $this->log = new Logs();
    }

    /**
     * 合成后文件地址前缀
     */
    public function getPrefix()
    {
        $prefix = 'uploads/' . date('Ymd', time()) . '/';
        if (!file_exists($prefix)) {
            mkdir($prefix, 0777);
        }
        return $prefix;
    }

    /**
     * 获取视频的宽高
     */
    public function getVideoRadio($link)
    {
        //ffmpeg -i /www/liujiu/quanzi/public/uploads/20200813/2020081322071619.mp4 2>&1
        try {
            $e = $this->ffmpeg;
            $e .= " -i ";
            $e .= $this->prefix.$link;
            $e .= " 2>&1";
            $this->log->setFFmpeg($e);
            $info = shell_exec($e);
            if (!$info) {
                return array('code'=>'-1','msg'=>'no link');
            }
            $info2s = explode("\n",$info);
            $w = 0; $h = 0;
            //获取指定行信息
            $streams = array();
            foreach ($info2s as $info2) {
                if (strpos($info2,'Stream')!==false && strpos($info2,'Video')!==false) {
                    $streams = explode(" ",$info2);
                }
            }
            //转化为数组
            $radios = array();
            if ($streams) {
                foreach ($streams as $str) {
                    $str = trim($str);
                    if ($str) {
                        $str = trim($str,','); $str = trim($str,')');
                        if (preg_match("/\d+x\d+/",$str,$match)) {
                            $strs = explode('x',$str);
                            if ($strs[0] && $strs[1]) {
                                $radios[] = $str; $w = $strs[0]; $h = $strs[1];
                            }
                        }
                    }
                }
            }
            if (!$w || !$h) {
                return array('code'=>'-2','msg'=>'w h error');
            }
            return array('code'=>'0','msg'=>'success','w'=>$w,'h'=>$h);
        } catch (\Exception $e) {
            return array('code'=>'-1','msg'=>'error'.$e);
        }
    }

    /**
     * 获取视频的帧率
     */
    public function getVideoFps($link)
    {
        //ffmpeg -i /www/liujiu/quanzi/public/uploads/20200813/2020081322071619.mp4 2>&1
        try {
            $e = $this->ffmpeg;
            $e .= " -i ";
            $e .= $this->prefix.$link;
            $e .= " 2>&1";
            $this->log->setFFmpeg($e);
            $info = shell_exec($e);
            if (!$info) {
                return array('code'=>'-1','msg'=>'no link');
            }
            $info2s = explode("\n",$info);
            //return $info2s;
            //获取指定行信息
            $streams = array();
            foreach ($info2s as $info2) {
                if (strpos($info2,'Stream')!==false && strpos($info2,'Video')!==false) {
                    $streams = explode(" ",$info2);
                }
            }
            //return $streams;
            $fps = 0; $fpsKey = 21;
            if (isset($streams[$fpsKey]) && $streams[$fpsKey]) {
                $fps = $streams[$fpsKey];
            }
            return array('code'=>'0','msg'=>'success','fps'=>$fps);
        } catch (\Exception $e) {
            return array('code'=>'-1','msg'=>'error'.$e);
        }
    }

    /**
     * 获取时长
     */
    public function getVideoDelay($link)
    {
        try {
            $e = $this->ffmpeg;
            $e .= " -i ";
            $e .= $this->prefix.$link;
            $e .= " 2>&1";
            $this->log->setFFmpeg($e);
            $info = shell_exec($e);
            if (!$info) { return array('code'=>'-2','msg'=>'no link'); }
            //获取视频时长、开始时间、码率
            if (preg_match("/Duration: (.*?), start: (.*?), bitrate: (\d*) kb\/s/", $info, $match)) {
                $s = $match[1]; $ss = explode(":",$s); $miao = floor($ss[2]);
                return array('code'=>'0','msg'=>'success','data'=>$miao);
            }
            return array('code'=>'-3','msg'=>'match error');
        } catch (\Exception $e) {
            return array('code'=>'-1','msg'=>'error'.$e);
        }
    }

    /**
     * 获取视频封面图片
     * @param string $mp4 视频文件地址
     * @param int $time 截图的秒数
     * @param int $width 图片宽度
     * @param int $height 图片高度
     */
    function getVideoCover($mp4, $time=1, $w=720, $h=1280)
    {
        //ffmpeg -i /www/liujiu/quanzi/public/uploads/202007/001.mp4 -y -f image2 -t 1 -s 720x1280 /www/liujiu/quanzi/public/uploads/202007/001.png
        try {
            if (!$mp4) { return array('code'=>'-2','msg'=>'no link'); }
            $prefix = $this->getPrefix();
            $filePath = $prefix.'cover'.date('YmdHis',time()).uniqid().".png";
            //拼接指令字符串
            $e = $this->ffmpeg;
            $e .= " -i ".$mp4;
            $e .= " -y -f image2 -t ";
            $e .= " {$time} -s {$w}x{$h} ";
            $e .= " ".$this->prefix.$filePath;
            $this->log->setFFmpeg($e);
            exec($e);
            return array('code'=>'0','msg'=>'success','data'=>$filePath);
        } catch (\Exception $e) {
            return array('code'=>'-1','msg'=>'error'.$e);
        }
    }

    /**
     * 把mp4压缩成GIF，1秒开始，截取-4秒
     * @param $mp4原视频地址，$w指定宽度，$h指定高度
     */
    public function setMp4ToGif($mp4,$w,$h,$t=4)
    {
        //ffmpeg -ss 2 -t 5 -i /www/liujiu/quanzi/public/uploads/202007/01.mp4 -s 272x480 -r 15 /www/liujiu/quanzi/public/uploads/2020/11.gif
        try {
            $prefix = $this->getPrefix();
            $fns = explode('/',$mp4); $fname = $fns[count($fns)-1];
            $ms = explode('.',$fname); $m = $ms[0];
            $filePath = $prefix.$m.".gif";
            $t = $t - 1;
            //拼接指令字符串
            $e = $this->ffmpeg;
            $e .= " -ss 1 -t ".$t." -i ".$this->prefix.$mp4;
            $e .= " -s ".$w.'*'.$h;
            $e .= " -r 15 ".$this->prefix.$filePath;
            $this->log->setFFmpeg($e);
            exec($e);
            return array('code'=>'0','msg'=>'success','data'=>$filePath);
        } catch (\Exception $e) {
            return array('code'=>'-1','msg'=>'error'.$e);
        }
    }

    /**
     * 把mp4压缩成GIF，1秒开始，截取-4秒
     * @param $mp4原视频地址，$w指定宽度，$h指定高度，$delay指定时长
     */
    public function setMp4ToGifV2($mp4,$w,$h,$delay)
    {
        //ffmpeg -ss 2 -t 20 -i /www/liujiu/quanzi/public/uploads/202007/01.mp4 -s 272x480 -r 15 /www/liujiu/quanzi/public/uploads/2020/11.gif
        try {
            $prefix = $this->getPrefix();
            $fns = explode('/',$mp4); $fname = $fns[count($fns)-1];
            $ms = explode('.',$fname); $m = $ms[0];
            $filePath = $prefix.$m.".gif";
            //拼接指令字符串
            $e = $this->ffmpeg;
            $e .= " -ss 1 -t ".$delay." -i ".$this->prefix.$mp4;
            $e .= " -s ".$w.'*'.$h;
            $e .= " -r 15 ".$this->prefix.$filePath;
            $this->log->setFFmpeg($e);
            exec($e);
            return array('code'=>'0','msg'=>'success','data'=>$filePath);
        } catch (\Exception $e) {
            return array('code'=>'-1','msg'=>'error'.$e);
        }
    }

    /**
     * 图片缩略图
     * @param $img原图片地址，$w指定宽度，$h指定高度
     */
    public function setImgToSize($image,$w,$h)
    {
        try {
            $images = explode("/",$image);
            $imageName = $images[count($images)-1];
            $exts = explode(".",$imageName);
            $fname = $exts[0]; $fext = $exts[1];
            $imgPath = $this->getPrefix().$fname.'x.'.$fext;
            $type = strtolower(substr(strrchr($image,'.'),1));
            $img = '';
            if($type=='jpg' || $type=='jpeg'){
                $img = imagecreatefromjpeg($image);
            }
            if($type=='gif'){
                $img = imagecreatefromgif($image);
            }
            if($type=='png'){
                $img = imagecreatefrompng($image);
            }
            if (!$img) {
                return array('code'=>'-2','msg'=>'image type error');
            }
            $imagex = imagesx($img); $imagey = imagesy($img);
            $newimg = imagecreatetruecolor($w, $h);
            imagecopyresampled($newimg,$img,0,0,0,0,$w,$h,$imagex,$imagey);
            imagejpeg($newimg,$imgPath,100);
            return array('code'=>'0','msg'=>'success','data'=>$imgPath);
        } catch (\Exception $e) {
            return array('code'=>'-1','msg'=>'error'.$e);
        }
    }

    /**
     * 把mp4转为mp3
     */
    public function setAmrToMp3($amr)
    {
        //ffmpeg -i /www/liujiu/quanzi/public/uploads/2020/2020082322512118.amr /www/liujiu/quanzi/public/uploads/2020/2020082322512118.mp3
        try {
            $prefix = substr($amr, 0, -3);
            $filePath = $prefix.'mp3';
            //拼接指令字符串
            $e = $this->ffmpeg;
            $e .= " -i ".$this->prefix.$amr;
            $e .= " ".$this->prefix.$filePath;
            $this->log->setFFmpeg($e);
            exec($e);
            return array('code'=>'0','msg'=>'success','data'=>$filePath);
        } catch (\Exception $e) {
            return array('code'=>'-1','msg'=>'error'.$e);
        }
    }

    /**
     * 把mp4压缩成指定的宽高
     * @param $mp4原视频地址，$w指定宽度，$h指定高度
     */
    public function setMp4ToSize($mp4,$w,$h)
    {
        //ffmpeg -y -i /www/liujiu/quanzi/public/uploads/2020/11.mp4 -s 100*200 /www/liujiu/quanzi/public/uploads/2020/11xx.mp4
        try {
            $prefix = $this->getPrefix();
            $filePath = $prefix.time().rand(100,999).".mp4";
            //拼接指令字符串
            $e = $this->ffmpeg;
            $e .= " -y -i ".$this->prefix.$mp4;
            $e .= " -s ".$w.'*'.$h." ";
            $e .= $this->prefix.$filePath;
            $this->log->setFFmpeg($e);
            exec($e);
            return array('code'=>'0','msg'=>'success','data'=>$filePath);
        } catch (\Exception $e) {
            return array('code'=>'-1','msg'=>'error');
        }
    }

    /**
     * 把mp4裁剪成指定的宽高
     * @param $mp4原视频地址，$w指定宽度，$h指定高度
     */
    public function setMp4ToCrop($mp4,$w,$h)
    {
        //ffmpeg -i /www/liujiu/quanzi/public/uploads/input.mp4 -vf crop=w:h:0 -y /www/liujiu/quanzi/public/uploads/out.mp4
        try {
            $prefix = $this->getPrefix();
            $filePath = $prefix.time().rand(100,999).".mp4";
            //拼接指令字符串
            $e = $this->ffmpeg;
            $e .= " -i ".$this->prefix.$mp4;
            $e .= " -vf ";
            $e .= " crop=".$w.":".$h.":0 ";
            $e .= " -y ".$this->prefix.$filePath;
            $this->log->setFFmpeg($e);
            shell_exec($e);
            return array('code'=>'0','msg'=>'success','data'=>$filePath);
        } catch (\Exception $e) {
            return array('code'=>'-1','msg'=>'error');
        }
    }

    /**
     * MP4音视频中分离出音频
     */
    public function setMp4SplitMp3($mp4)
    {
        //ffmpeg -i /www/liujiu/quanzi/public/uploads/input.mp4 -y /www/liujiu/quanzi/public/uploads/out.mp3
        try {
            $prefix = $this->getPrefix();
            $filePath = $prefix.time().rand(100,999).".mp3";
            //拼接指令字符串
            $e = $this->ffmpeg;
            $e .= " -i ".$this->prefix.$mp4;
            $e .= " -y ".$this->prefix.$filePath;
            $this->log->setFFmpeg($e);
            shell_exec($e);
            return array('code'=>'0','msg'=>'success','data'=>$filePath);
        } catch (\Exception $e) {
            return array('code'=>'-1','msg'=>'error');
        }
    }

    /**
     * MP4音视频中分离出视频
     */
    public function setMp4SplitMp4($mp4)
    {
        //ffmpeg -i /www/liujiu/quanzi/public/uploads/input.mp4 -vcodec copy -an -y /www/liujiu/quanzi/public/uploads/out.mp4
        try {
            $prefix = $this->getPrefix();
            $filePath = $prefix.time().rand(100,999).".mp4";
            //拼接指令字符串
            $e = $this->ffmpeg;
            $e .= " -i ".$this->prefix.$mp4;
            $e .= " -vcodec copy -an ";
            $e .= " -y ".$this->prefix.$filePath;
            $this->log->setFFmpeg($e);
            shell_exec($e);
            return array('code'=>'0','msg'=>'success','data'=>$filePath);
        } catch (\Exception $e) {
            return array('code'=>'-1','msg'=>'error');
        }
    }

    /**
     * 视频音频合成
     */
    public function setMp4Mp3ToMp4($mp4,$mp3,$t=0)
    {
        //ffmpeg -i /www/liujiu/quanzi/public/input.mp3 -i /www/liujiu/quanzi/public/input.mp4 -t 3 -y /www/liujiu/quanzi/public/out.mp4
        try {
            $prefix = $this->getPrefix();
            $filePath = $prefix.time().rand(100,999).".mp4";
            //拼接指令字符串
            $e = $this->ffmpeg;
            $e .= " -i ".$this->prefix.$mp4;
            $e .= " -i ".$this->prefix.$mp3;
            if ($t) { $e .= " -t ".$t." "; }
            $e .= " -y ".$this->prefix.$filePath;
            $this->log->setFFmpeg($e);
            shell_exec($e);
            return array('code'=>'0','msg'=>'success','data'=>$filePath);
        } catch (\Exception $e) {
            return array('code'=>'-1','msg'=>'error');
        }
    }
}